package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private VodService vodService;
	@Autowired
	private UserInfoFeignClient userInfoFeignClient;


	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount, Long userId) {
		//  声明一个集合；
		List<TrackInfo> trackInfoList = new ArrayList<>();
		//  1.  获取用户购买过的声音列表;
		//  通过声音Id获取到声音对象中的专辑Id
		TrackInfo trackInfo = this.getById(trackId);
		Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
		//  判断返回数据集
		Assert.notNull(userPaidTrackList, "查询用户购买声音列表失败");
		//  这个集合可以为空.
		List<Long> userPaidTrackIdList = userPaidTrackList.getData();

		//  判断当前购买的集数;
		if (0 == trackCount) {
			//  购买的是本集；
			trackInfoList.add(trackInfo);
		} else {
			//  设置查询条件;
			LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
			wrapper.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum())
					.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId());
			if (!CollectionUtils.isEmpty(userPaidTrackIdList)) {
				//  排除用户已购买的声音Id;
				wrapper.notIn(TrackInfo::getId, userPaidTrackIdList);
			}
			wrapper.last(" limit " + trackCount);
			//  查询数据;
			trackInfoList = trackInfoMapper.selectList(wrapper);
		}
		//  返回数据;
		return trackInfoList;

	}

	@Override
	public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
		List<Map<String, Object>> list = new ArrayList<>();
		// 获取声音信息
		TrackInfo trackInfo = this.getById(trackId);
		// 获取声音的排序值
		Integer orderNum = trackInfo.getOrderNum();
		// 获取当前用户购买的声音列表
		Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
		Assert.notNull(trackIdListResult, "查询用户购买声音列表失败");
		List<Long> trackIdList = trackIdListResult.getData();

		//  从当前声音Id开始计算有多少声音是需要付费的集合Id;
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
				.gt(TrackInfo::getOrderNum, orderNum));

		//  两个集合取差集,需要付费的声音列表;
		List<TrackInfo> paidTrackIdList = trackInfoList.stream().filter(trackInfoItem -> !trackIdList.contains(trackInfoItem.getId())).collect(Collectors.toList());

		//  根据专辑Id获取专辑对象
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		//  判断
		if (paidTrackIdList.size() >= 0) {
			//  显示本集;   [本集]
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "本集");
			//  当前每一集声音的钱数;
			map.put("price", albumInfo.getPrice());
			map.put("trackCount", 0);
			//  添加本集到集合;
			list.add(map);
		}
		//  后9集（本集之后，0<需要付费集数<=10）  【本集】【后（1-10）集】
		if (paidTrackIdList.size() > 0 && paidTrackIdList.size() <= 10) {
			//  显示后size集;
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后" + paidTrackIdList.size() + "集");
			//  当前每一集声音的钱数;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
			map.put("trackCount", paidTrackIdList.size());
			//  添加本集到集合;
			list.add(map);
		}
		//  后10集;（本集之后，需要付费集数>10）  【本集】【后10集】【后（11-20）集】
		if (paidTrackIdList.size() > 10) {
			//  后10集合;
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后10集");
			//  当前每一集声音的钱数;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal("10")));
			map.put("trackCount", 10);
			//  添加本集到集合;
			list.add(map);
		}

		//  后19集（本集之后，10<需要付费集数<=20）  【本集】【后10集】【后（11-20）集】
		if (paidTrackIdList.size() > 10 && paidTrackIdList.size() <= 20) {
			//  显示后size集;
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后" + paidTrackIdList.size() + "集");
			//  当前每一集声音的钱数;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
			map.put("trackCount", paidTrackIdList.size());
			//  添加本集到集合;
			list.add(map);
		}
		//  后20集;（本集之后，需要付费集数>20）  【本集】【后10集】【后20集】
		if (paidTrackIdList.size() > 20) {
			//  后10集合;
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后20集");
			//  当前每一集声音的钱数;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal("20")));
			map.put("trackCount", 20);
			//  添加本集到集合;
			list.add(map);
		}
		// 返回数据
		return list;
	}

	@Override
	public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
		//
		// 判断统计类型是播放量
		if(SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())){
			// 1.  更新声音播放数--调用更新方法
			trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(), trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
			// 2.  更新专辑播放数统计表--调用更新方法
			albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(), trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY);

		} else if(SystemConstant.TRACK_STAT_COLLECT.equals(trackStatMqVo.getStatType())){

		}

	}

	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
		// 1.  需要先根据专辑Id获取到声音列表;
		IPage<AlbumTrackListVo> albumTrackListVoIPage = trackInfoMapper.selectAlbumTrackList(albumTrackListVoPage, albumId);
		//  查询专辑类型:
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		//  判断用户是否登录;
		if (null == userId) {
			// 用户没登录;
			//专辑类型是付费和vip免费时（专辑类型不是免费），除免费试听声音都需要付费;
			if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
				//  免费试听集数; 5
				Integer tracksForFree = albumInfo.getTracksForFree();
				//  除免费试听声音都需要付费;   声音列表的order_num > tracksForFree 的 setIsShowPaidMark(true)增加付费标识
				albumTrackListVoIPage.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree).forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
			}
		} else {
			//  用户登录;
			//获取用户信息
			Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
			Assert.notNull(userInfoVoResult, "查询用户信息失败");
			UserInfoVo userInfoVo = userInfoVoResult.getData();
			Assert.notNull(userInfoVo, "查询用户信息失败");
			//  声明一个变量;记录是否需要付费; false: 免费； true: 付费
			boolean isPaid = false;
			//对于vip免费的专辑类型。用户不是vip或者vip过期时，除免费试听声音都需要付费;
			if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
				//  用户是vip&&vip过期 || 用户不是vip
				if ((userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date())) || userInfoVo.getIsVip() == 0) {
					//  需要付费;
					isPaid = true;
				} //面对专辑类型是付费类型，除免费试听声音都需要付费;
			}else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
				//  必须付费：
				isPaid = true;
			}
			//  判断需要付费的专辑情况：
			if (isPaid) {
				//  远程调用，需要知道用户购买了该专辑的哪些声音; 专辑Id; 付费声音列表 = 该专辑下的声音列表：albumTrackListVoIPage > 试听部分  ;userId--从本地线程中获取;
				List<AlbumTrackListVo> albumTrackListVoList = albumTrackListVoIPage.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
				//  付费声音Id列表
				List<Long> trackIdList = albumTrackListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
				//	获取用户购买的声音列表; 如果用户购买了； 将购买的声音Id与状态存储到map集合中; map.put(trackId,1)-买过; map.put(trackId,0)-未买过;
				Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
				Assert.notNull(mapResult, "查询用户购买声音失败");
				Map<Long, Integer> map = mapResult.getData();
				// 遍历付费声音列表
				for (AlbumTrackListVo albumTrackListVo : albumTrackListVoList) {
					//  Boolean isPaidMark1 = map.get(albumTrackListVo.getTrackId()) == 0 ? true : false;
					//  默认是isShowPaidMark = false;
					// 没买过这条声音，getTrackId() == 0，为ture，setIsShowPaidMark付费标识改为true
					albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 0);
				}
			}
		}
			return  albumTrackListVoIPage;
	}

	@Override
	public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
		TrackInfo trackInfo = this.getById(trackId);
		//获取原始的文件Id
		String originMediaFileId = trackInfo.getMediaFileId();
		//属性拷贝赋值
		BeanUtils.copyProperties(trackInfoVo, trackInfo);
		//	判断声音是否被修改;
		if (!originMediaFileId.equals(trackInfoVo.getMediaFileId())) {
			//	修改了声音;
			TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
			//	赋值最新流媒体数据;
			trackInfo.setMediaType(mediaInfo.getType());
			trackInfo.setMediaDuration(mediaInfo.getDuration());
			trackInfo.setMediaSize(mediaInfo.getSize());
			trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
			//	原有云视频删除
			vodService.deleteMedia(originMediaFileId);
		}
		//	更新数据
		this.updateById(trackInfo);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfo(Long trackId) {
		//	查询当前声音对象;
		TrackInfo trackInfo = this.getById(trackId);
		//	删除track_info数据
		trackInfoMapper.deleteById(trackId);
		//	删除track_stat数据
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
		//	album_info 更新 include_track_count
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		//	删除一条数据；
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
		//	需要更新记录;
		albumInfoMapper.updateById(albumInfo);
		//	在重新管理一下 order_num;
		trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
		//	删除云点播中没有用的声音记录;
		vodService.deleteMedia(trackInfo.getMediaFileId());
	}

	@Override
	public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
		//	调用mapper 层方法
		return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
		try {
			//	track_info track_stat album_info;
			TrackInfo trackInfo = new TrackInfo();
			//	有相同的属性值，进行属性拷贝;
			BeanUtils.copyProperties(trackInfoVo, trackInfo);
			//	赋值用户Id
			trackInfo.setUserId(userId);
			//	order_num; 第一种查询当前专辑对应的声音集数+1; 第二种：查询专辑包含声音总数+1;
			AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
			trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
			//	处理流媒体的数据; 时长，类型这些数据页面没有传递；fileId 查询流媒体数据，然后赋值：调用云点播的api;
			TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
			//	赋值：
			trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
			trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
			trackInfo.setMediaType(trackMediaInfoVo.getType());
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			//	保存声音结束;
			trackInfoMapper.insert(trackInfo);
			//	track_stat
			saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
			saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
			saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
			saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
			//	album_info; 更新数据;
			albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
			//	更新操作;
			albumInfoMapper.updateById(albumInfo);
		} catch (BeansException e) {
			log.error("保存声音信息失败：{}", e);
			throw new RuntimeException(e);
		}
	}

	/**
	 * 保存声音统计数据
	 * @param trackId
	 * @param statPlay
	 */
	public void saveTrackStat(Long trackId, String statPlay) {
		TrackStat trackStat = new TrackStat();
		//	赋值
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statPlay);
		trackStat.setStatNum(new Random().nextInt(1000));
		//	数据保存
		trackStatMapper.insert(trackStat);
	}

}
